<?php

class Store_Paginator extends Zend_Paginator
{
	public $id_page;

	const CACHE_CONTROL_PAGE	= 'control_page';
	const CACHE_CONTROL_OBJECT	= 'control_object';
	
	/**
	 * Factory.
	 * @param  int $id_page
	 * @param  mixed $data
	 * @param  string $adapter
	 * @param  array $prefixPaths
	 * @return Job_Paginator
	 */
	public static function pageFactory($id_page, $data, $adapter = self::INTERNAL_ADAPTER, array $prefixPaths = null)
	{
		$paginator = self::factory($data, $adapter, $prefixPaths);

		$paginator->id_page = $id_page;
		$paginator->setCache(YouNet_Util::getObjectMemCache());
		$paginator->setCacheEnabled(true);
		return $paginator;
	}
	
	/**
	 *
	 * @param type $data
	 * @param type $adapter
	 * @param array $prefixPaths
	 * @return Job_Paginator 
	 */
	public static function factory($data, $adapter = self::INTERNAL_ADAPTER, array $prefixPaths = null)
	{
		   if ($data instanceof Zend_Paginator_AdapterAggregate) {
            return new self($data->getPaginatorAdapter());
        } else {
            if ($adapter == self::INTERNAL_ADAPTER) {
                if (is_array($data)) {
                    $adapter = 'Array';
                } else if ($data instanceof Zend_Db_Table_Select) {
                    $adapter = 'DbTableSelect';
                } else if ($data instanceof Zend_Db_Select) {
                    $adapter = 'DbSelect';
                } else if ($data instanceof Iterator) {
                    $adapter = 'Iterator';
                } else if (is_integer($data)) {
                    $adapter = 'Null';
                } else {
                    $type = (is_object($data)) ? get_class($data) : gettype($data);

                    /**
                     * @see Zend_Paginator_Exception
                     */
                    require_once 'Zend/Paginator/Exception.php';

                    throw new Zend_Paginator_Exception('No adapter for type ' . $type);
                }
            }

            $pluginLoader = self::getAdapterLoader();

            if (null !== $prefixPaths) {
                foreach ($prefixPaths as $prefix => $path) {
                    $pluginLoader->addPrefixPath($prefix, $path);
                }
            }

            $adapterClassName = $pluginLoader->load($adapter);

            return new self(new $adapterClassName($data));
        }
	}	

	public function getItemsByPage($pageNumber)
	{
		$pageNumber = $this->normalizePageNumber($pageNumber);
		$key = $this->_getCacheId($pageNumber);

		if ($this->_cacheEnabled())
		{
			$data = self::$_cache->load($key);
			if ($data !== false)
			{
				return $data;
			}
		}

		$offset = ($pageNumber - 1) * $this->getItemCountPerPage();

		$items = $this->_adapter->getItems($offset, $this->getItemCountPerPage());

		$filter = $this->getFilter();

		if ($filter !== null)
		{
			$items = $filter->filter($items);
		}

		if (!$items instanceof Traversable)
		{
			$items = new ArrayIterator($items);
		}

		if ($this->_cacheEnabled())
		{
			self::$_cache->save($items, $key);
			$this->_addCacheControl($items, $key);
		}

		return $items;
	}

	private function _addCacheControl($items, $key)
	{
		foreach ($items as $item)
		{
			$cache_control_object = self::$_cache->load(self::CACHE_CONTROL_OBJECT . $item->id);
			$cache_control_object[] = $key;
			self::$_cache->save($cache_control_object, self::CACHE_CONTROL_OBJECT . $item->id);
		}

		$cache_control_page = self::$_cache->load(self::CACHE_CONTROL_PAGE . $this->id_page);
		$cache_control_page[] = $key;
		self::$_cache->save($cache_control_page, self::CACHE_CONTROL_PAGE . $this->id_page);
	}

	public static function invalidateCacheByIdModel($id_model)
	{
		$cache_control_model = YouNet_Util::getObjectMemCache()->load(self::CACHE_CONTROL_OBJECT . $id_model);
		if ($cache_control_model)
		{
			foreach ($cache_control_model as $key)
			{
				YouNet_Util::getObjectMemCache()->remove($key);
			}
			YouNet_Util::getObjectMemCache()->remove(self::CACHE_CONTROL_OBJECT . $id_model);
		}
	}

	public static function invalidateCacheByIdPage($id_page)
	{
		$cache_control_page = YouNet_Util::getObjectMemCache()->load(self::CACHE_CONTROL_PAGE . $id_page);
		if ($cache_control_page)
		{
			foreach ($cache_control_page as $key)
			{
				YouNet_Util::getObjectMemCache()->remove($key);
			}
			YouNet_Util::getObjectMemCache()->remove(self::CACHE_CONTROL_PAGE . $id_page);
		}
	}

}